package xcollections;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.lang.reflect.Method;


public class Xtask implements java.io.Serializable{
	
	//returns the name of the type of the collection 
	void getCollectionName(Collection unknownCollection) {
		System.out.println("The class of " + unknownCollection +
                " is " + unknownCollection.getClass().getName());
	}

	//finds the main type of Objects in the collection
	Object findMainType(Collection unknownCollection) {
		
		String typeOfFirstObj = "";
		String typeOfSecondObj = "";
		String mainType = "";
		Object main = null;
		Iterator iter = unknownCollection.iterator();
		while (iter.hasNext()) {
			Object element = iter.next();
			typeOfFirstObj = element.getClass().getName();
			
			if (typeOfFirstObj.equals(typeOfSecondObj)) {
				mainType = typeOfFirstObj;
				main = element;
				break;
			}
			mainType = typeOfFirstObj;
			typeOfSecondObj = mainType;
		} return main;
	}
	
	//creates another collection (copy of 1st), and removes the black sheep from it
	Collection removeBlackSheep(Collection unknownCollection, Object mainType) {
		if (unknownCollection == null || mainType == null) {
			throw new IllegalArgumentException();
		}
		Collection secondCollection = null;
		try {
			String someClass = unknownCollection.getClass().getName();
			Class myclass = Class.forName(someClass);
	        secondCollection = (Collection) myclass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		for (Object o : unknownCollection) {
			if (o.getClass().equals(mainType.getClass()))
				secondCollection.add(o);
			else
				continue;
		}
		return secondCollection;		
	}
	
	//prints the name of the methods, which the given class in the collection has
	void printMethodsFromClass(Collection unknownCollection) {
		if (unknownCollection != null){
			Method [] methods = null;
			for (Object o : unknownCollection) {
				methods = o.getClass().getDeclaredMethods();
				break;
			}for (Method method : methods) {
				System.out.println(method.getName());
			}
		}	
	}
	
	//print all objects in collection
	void printObjectsInCollection(Collection unknownCollection) {
		if (unknownCollection != null)
			for (Object o:unknownCollection) {
				System.out.println(o.getClass().getName());
			}
	}
	
	void serializeAndSend(Collection unknownCollection) {
		try{
			 // Serialize data object to a file
			 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Xtask.java"));
			 out.writeObject(unknownCollection);
			 out.close();
			 // Serialize data object to a byte array
//			 ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
//			 out = new ObjectOutputStream(bos) ;
//			 out.writeObject(unknownCollection);
//			 out.close();
//			 // Get the bytes of the serialized object
//			 byte[] buf = bos.toByteArray();
//			 System.out.println("DOne");
		} catch (IOException e) {
			 System.out.println("Done1");
		}
	}

	public static void main(String[] args) throws Exception {
		
		Xtask task = new Xtask();
				
		ArrayList glist = new ArrayList();
		task.getCollectionName(glist);
		
		Opit o1 = new Opit();
		Opit o2 = new Opit();
		Opit o3 = new Opit();
		Opit2 o4 = new Opit2();
		glist.add(o1);
		glist.add(o2);
		glist.add(o3);
		glist.add(o4);
		
		task.serializeAndSend(glist);
		Object main = task.findMainType(glist);
		Collection secondCollection = task.removeBlackSheep(glist, main);
		task.printObjectsInCollection(secondCollection);
		System.out.println();
		task.printMethodsFromClass(glist);
		
	}

}
